/**
 * 通知状态管理服务 - 单例模式
 * 统一管理通知数据的获取和更新,避免重复请求
 */

import { ref, type Ref } from "vue";
import {
  getNotificationStatsApi,
  getLatestNotificationsApi,
  type NotificationStats,
  type NotificationDetail
} from "@/api/notification";

/** 通知服务类 */
class NotificationService {
  /** 单例实例 */
  private static instance: NotificationService | null = null;

  /** 通知统计数据 */
  private stats: Ref<NotificationStats | null> = ref(null);

  /** 最新通知列表 */
  private latestNotifications: Ref<NotificationDetail[]> = ref([]);

  /** 正在加载统计数据 */
  private loadingStats = false;

  /** 正在加载最新通知 */
  private loadingLatest = false;

  /** 定时器ID */
  private pollingTimer: number | null = null;

  /** 轮询间隔(毫秒) */
  private pollingInterval = 30000; // 30秒

  /** 页面不可见时的轮询间隔(毫秒) */
  private inactivePollingInterval = 120000; // 2分钟

  /** 页面是否可见 */
  private isPageVisible = true;

  /** 用户最后活动时间 */
  private lastUserActivity = Date.now();

  /** 用户无活动超时时间(毫秒) */
  private userInactiveTimeout = 300000; // 5分钟

  /** 订阅者列表 - 用于通知数据更新 */
  private subscribers: Set<(stats: NotificationStats) => void> = new Set();

  /** 最新通知订阅者 */
  private latestSubscribers: Set<
    (notifications: NotificationDetail[]) => void
  > = new Set();

  /** 最后一次请求时间 */
  private lastStatsRequestTime = 0;

  /** 最后一次通知请求时间 */
  private lastLatestRequestTime = 0;

  /** 请求去重间隔(毫秒) - 在此时间内的重复请求会被忽略 */
  private dedupeInterval = 15000; // 🔑 优化: 从5秒增加到15秒，大幅减少重复请求

  /** WebSocket 是否已连接 */
  private webSocketConnected = false;

  /** visibilitychange 防抖定时器 */
  private visibilityDebounceTimer: number | null = null;

  /** visibilitychange 防抖延迟(毫秒) */
  private visibilityDebounceDelay = 1000; // 🔑 1秒防抖，避免快速切换时多次触发

  /** 私有构造函数,防止外部实例化 */
  private constructor() {
    // 初始状态为null,等待第一次加载
    // 这样组件可以知道数据还没有加载

    // 监听页面可见性变化
    this.setupVisibilityListener();

    // 监听用户活动
    this.setupUserActivityListener();
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): NotificationService {
    if (!NotificationService.instance) {
      NotificationService.instance = new NotificationService();
    }
    return NotificationService.instance;
  }

  /**
   * 获取统计数据的响应式引用
   */
  public getStatsRef(): Ref<NotificationStats | null> {
    return this.stats;
  }

  /**
   * 获取最新通知的响应式引用
   */
  public getLatestNotificationsRef(): Ref<NotificationDetail[]> {
    return this.latestNotifications;
  }

  /**
   * 订阅统计数据更新
   * @param callback 回调函数
   * @returns 取消订阅的函数
   */
  public subscribe(callback: (stats: NotificationStats) => void): () => void {
    this.subscribers.add(callback);
    // 如果已有数据,立即通知
    if (this.stats.value) {
      callback(this.stats.value);
    }
    // 返回取消订阅函数
    return () => {
      this.subscribers.delete(callback);
    };
  }

  /**
   * 订阅最新通知更新
   * @param callback 回调函数
   * @returns 取消订阅的函数
   */
  public subscribeLatest(
    callback: (notifications: NotificationDetail[]) => void
  ): () => void {
    this.latestSubscribers.add(callback);
    // 如果已有数据,立即通知
    if (this.latestNotifications.value.length > 0) {
      callback(this.latestNotifications.value);
    }
    // 返回取消订阅函数
    return () => {
      this.latestSubscribers.delete(callback);
    };
  }

  /**
   * 通知所有订阅者
   */
  private notifySubscribers() {
    if (this.stats.value) {
      this.subscribers.forEach(callback => {
        try {
          callback(this.stats.value!);
        } catch (error) {
          console.error("通知订阅者失败:", error);
        }
      });
    }
  }

  /**
   * 通知最新通知订阅者
   */
  private notifyLatestSubscribers() {
    this.latestSubscribers.forEach(callback => {
      try {
        callback(this.latestNotifications.value);
      } catch (error) {
        console.error("通知最新通知订阅者失败:", error);
      }
    });
  }

  /**
   * 加载通知统计数据
   * @param force 是否强制刷新(忽略去重)
   */
  public async loadStats(force = false): Promise<NotificationStats | null> {
    const now = Date.now();

    // 🔑 去重检查:如果距离上次请求不到15秒,且不是强制刷新,则跳过
    if (
      !force &&
      this.lastStatsRequestTime > 0 &&
      now - this.lastStatsRequestTime < this.dedupeInterval
    ) {
      const remainingTime = Math.ceil(
        (this.dedupeInterval - (now - this.lastStatsRequestTime)) / 1000
      );
      console.log(
        `⏭️ 跳过重复的统计请求(距离上次请求小于15秒，还需等待${remainingTime}秒)`
      );
      return this.stats.value;
    }

    // 如果正在加载,返回现有数据
    if (this.loadingStats) {
      console.log("⏳ 统计数据正在加载中,跳过重复请求");
      return this.stats.value;
    }

    this.loadingStats = true;
    this.lastStatsRequestTime = now;

    try {
      const response = await getNotificationStatsApi();
      if (response.code === 200 && response.data) {
        this.stats.value = response.data;
        this.notifySubscribers();
        console.log("✅ 通知统计数据已更新:", response.data);
        return response.data;
      }
      return null;
    } catch (error) {
      console.error("❌ 加载通知统计失败:", error);
      return null;
    } finally {
      this.loadingStats = false;
    }
  }

  /**
   * 加载最新通知列表
   * @param limit 限制数量
   * @param force 是否强制刷新
   */
  public async loadLatestNotifications(
    limit = 10,
    force = false
  ): Promise<NotificationDetail[]> {
    const now = Date.now();

    // 🔑 去重检查
    if (
      !force &&
      this.lastLatestRequestTime > 0 &&
      now - this.lastLatestRequestTime < this.dedupeInterval
    ) {
      const remainingTime = Math.ceil(
        (this.dedupeInterval - (now - this.lastLatestRequestTime)) / 1000
      );
      console.log(
        `⏭️ 跳过重复的最新通知请求(距离上次请求小于15秒，还需等待${remainingTime}秒)`
      );
      return this.latestNotifications.value;
    }

    // 如果正在加载,返回现有数据
    if (this.loadingLatest) {
      console.log("⏳ 最新通知正在加载中,跳过重复请求");
      return this.latestNotifications.value;
    }

    this.loadingLatest = true;
    this.lastLatestRequestTime = now;

    try {
      const response = await getLatestNotificationsApi(limit);
      if (response.code === 200 && response.data) {
        this.latestNotifications.value = response.data;
        this.notifyLatestSubscribers();
        console.log("✅ 最新通知已更新,共", response.data.length, "条");
        return response.data;
      }
      return [];
    } catch (error) {
      console.error("❌ 加载最新通知失败:", error);
      return [];
    } finally {
      this.loadingLatest = false;
    }
  }

  /**
   * 刷新所有数据
   */
  public async refresh(): Promise<void> {
    await Promise.all([
      this.loadStats(true),
      this.loadLatestNotifications(10, true)
    ]);
  }

  /**
   * 监听页面可见性变化
   */
  private setupVisibilityListener(): void {
    if (typeof document === "undefined") return;

    document.addEventListener("visibilitychange", () => {
      this.isPageVisible = !document.hidden;
      console.log(`👁️ 页面可见性变化: ${this.isPageVisible ? "可见" : "隐藏"}`);
    });
  }

  /**
   * 监听用户活动
   */
  private setupUserActivityListener(): void {
    if (typeof window === "undefined") return;

    const events = ["mousedown", "keydown", "scroll", "touchstart"];
    const updateActivity = () => {
      this.lastUserActivity = Date.now();
    };

    events.forEach(event => {
      window.addEventListener(event, updateActivity, { passive: true });
    });
  }

  /**
   * 检查用户是否活跃
   */
  private isUserActive(): boolean {
    return Date.now() - this.lastUserActivity < this.userInactiveTimeout;
  }

  /**
   * 获取当前应该使用的轮询间隔
   */
  private getCurrentPollingInterval(): number {
    // 页面不可见时,使用更长的间隔
    if (!this.isPageVisible) {
      return this.inactivePollingInterval;
    }

    // 用户不活跃时,使用更长的间隔
    if (!this.isUserActive()) {
      return this.inactivePollingInterval;
    }

    // 默认间隔
    return this.pollingInterval;
  }

  /**
   * 启动轮询
   * @param interval 轮询间隔(毫秒),默认30秒
   */
  public startPolling(interval?: number): void {
    if (interval) {
      this.pollingInterval = interval;
    }

    // 🔑 关键优化: 如果 WebSocket 已连接,则不启动轮询
    if (this.webSocketConnected) {
      console.log("✅ WebSocket 已连接,跳过轮询启动");
      return;
    }

    // 先清除已有定时器
    this.stopPolling();

    const currentInterval = this.getCurrentPollingInterval();
    console.log(
      `🔄 启动通知降级轮询,间隔 ${currentInterval / 1000} 秒 (WebSocket 未连接)`
    );

    // 立即加载一次
    this.loadStats();

    // 设置定时器,使用动态间隔
    this.pollingTimer = window.setInterval(() => {
      // 🔑 关键优化: 轮询过程中如果 WebSocket 连接,则停止轮询
      if (this.webSocketConnected) {
        console.log("✅ WebSocket 已连接,停止降级轮询");
        this.stopPolling();
        return;
      }

      const interval = this.getCurrentPollingInterval();

      // 如果间隔改变了,重新设置定时器
      if (interval !== currentInterval) {
        this.stopPolling();
        this.startPolling();
        return;
      }

      // 只在页面可见或用户活跃时轮询
      if (this.isPageVisible || this.isUserActive()) {
        this.loadStats();
      } else {
        console.log("⏸️ 页面不可见且用户不活跃,跳过本次轮询");
      }
    }, currentInterval);
  }

  /**
   * 停止轮询
   */
  public stopPolling(): void {
    if (this.pollingTimer !== null) {
      clearInterval(this.pollingTimer);
      this.pollingTimer = null;
      console.log("⏹️ 通知轮询已停止");
    }
  }

  /**
   * 设置 WebSocket 连接状态
   * @param connected 是否已连接
   */
  public setWebSocketConnected(connected: boolean): void {
    const wasConnected = this.webSocketConnected;
    this.webSocketConnected = connected;

    if (connected && !wasConnected) {
      // WebSocket 从断开到连接: 停止轮询
      console.log("🔌 WebSocket 已连接,停止降级轮询");
      this.stopPolling();
    } else if (!connected && wasConnected) {
      // 🔑 优化: WebSocket 断开时不再自动启动轮询，依赖 visibilitychange 机制
      console.log("⚠️ WebSocket 已断开，依赖页面可见性变化机制刷新数据");
      // this.startPolling(); // 已禁用自动轮询
    }
  }

  /**
   * 处理 WebSocket 推送的统计数据更新
   * @param stats 统计数据
   */
  public handleWebSocketStats(stats: NotificationStats): void {
    console.log("📨 收到 WebSocket 推送的统计数据:", stats);
    this.stats.value = stats;
    this.notifySubscribers();
  }

  /**
   * 更新未读数量(减少指定数量)
   * @param count 减少的数量
   */
  public decreaseUnreadCount(count = 1): void {
    if (this.stats.value) {
      this.stats.value.totalUnreadCount = Math.max(
        0,
        this.stats.value.totalUnreadCount - count
      );
      this.notifySubscribers();
    }
  }

  /**
   * 清空未读数量
   */
  public clearUnreadCount(): void {
    if (this.stats.value) {
      this.stats.value.totalUnreadCount = 0;
      this.stats.value.hasUnread = false;
      this.notifySubscribers();
    }
  }

  /**
   * 更新公告未读数量
   * @param count 未读数量
   */
  public updateAnnouncementUnread(count: number): void {
    if (this.stats.value) {
      this.stats.value.unreadAnnouncementCount = count;
      this.notifySubscribers();
    }
  }

  /**
   * 销毁服务(用于测试或清理)
   */
  public destroy(): void {
    this.stopPolling();
    this.subscribers.clear();
    this.latestSubscribers.clear();
    NotificationService.instance = null;
  }
}

// 导出单例实例
export const notificationService = NotificationService.getInstance();

// 导出类型
export type { NotificationStats, NotificationDetail };
